from django.db import models
from django.db import connection

from PIL import Image

from ceemtu.cetcore.models import *

class InvalidImageSize(Exception): pass

IMAGE_SIZES = (
    ((150, 150), 'small'),
    ((320,280), 'thumbnail'),
    ((640,480), 'normal'),
    ((1024, 768), 'big'),
    (None, 'original')
    )
IMAGE_SIZE_MAPPING = {}
for size, name in IMAGE_SIZES:
    IMAGE_SIZE_MAPPING[name] = size

def build_date_tree():
    result = []
    cursor = connection.cursor()
    cursor.execute("""
        select year, month, day, count(*) as filecount
        from cetphoto_photo
        group by year, month, day
        order by year, month, day
        """)
    row = cursor.fetchall()
    return row

class Photo(models.Model):
    """
    
    """
    title = models.CharField(max_length=200)
    project = models.ManyToManyField(Project, null = True, blank = True)
    description = models.TextField(null = True, blank = True)
    notes = models.TextField(null = True, blank = True)
    rating = models.IntegerField(choices = RATING_CHOICES, null = True, blank = True)
    categories = models.ManyToManyField(Category, null = True, blank = True)
    tags = models.ManyToManyField(Tag, null = True, blank = True)
    location = models.CharField(max_length=200, null = True, blank = True)
    photographer = models.CharField(max_length=200, null = True, blank = True)
    in_the_attic = models.BooleanField()
    based_on = models.ForeignKey('self', null = True, blank = True)
    flickr_id = models.CharField(max_length=200, null = True, blank = True)
    dateperiods = models.ManyToManyField(DatePeriod, editable = False, null = True, blank = True)
    
    ##########################################################
    #                      READ-ONLY
    ##########################################################
    file_entry = models.ForeignKey(FileEntry, editable = False)
    image_hash = models.CharField(max_length=200, null = True, editable = False)    
    date_added = models.DateTimeField(default=datetime.datetime.now, editable = False)
    date_of_creation = models.DateTimeField(null = True, editable = False)
    year = models.IntegerField(null = True, editable = False)
    month = models.IntegerField(null = True, choices = MONTHS_CHOICES, editable = False)
    day = models.IntegerField(null = True, editable = False)
    
    ##########################################################
    #                        EXIF
    ##########################################################
    shutter_speed = models.CharField(max_length=200, null = True, editable = False)
    aperture = models.CharField(max_length=200, null = True, editable = False)
    flash = models.BooleanField(null = True, editable = False)
    exposure_time = models.CharField(max_length=200, null = True, editable = False)
    camera_make = models.CharField(max_length=200, null = True, editable = False)
    camera_model = models.CharField(max_length = 200, null = True, editable = False)
    fnumber = models.CharField(max_length=10, null = True, editable = False)
    iso_speed = models.IntegerField(null = True, editable = False)
    orientation = models.CharField(max_length=200, null = True, editable = False)
    width = models.IntegerField(null = True, editable = False)
    height = models.IntegerField(null = True, editable = False)

    class Meta:
        verbose_name = "Photo"
        verbose_name_plural = "Photos"
        ordering = ['in_the_attic', '-date_of_creation', 'title']

    def create_thumbnails(self):
        """
        
        """
        for name, size in IMAGE_SIZE_MAPPING.items():
            if size:
                self.get_image(name)

    def thumbnail(self):
        return '<img src="/static/generated/%s"/>' % self.get_image('thumbnail')
    thumbnail.allow_tags = True

    def thumbnail_url(self):
        return '/static/generated/%s' % self.get_image('thumbnail')
    thumbnail_url.allow_tags = True

    def details(self):
        return '<a href="/photo/details/%s">%s</a>' % (self.id, self.title)
    details.allow_tags = True

    def details_url(self):
        return '/photo/details/%s' % self.id
    details_url.allow_tags = True

    def get_image(self, size):
        """
        
        """
        if not self.file_entry.exists():
            print "File not available"
            return None
        
        size = size.lower()
        if not self.image_hash:
            m = hashlib.sha1()
            m.update("%s%s%s%s%s" % (self.file_entry.archive.id, self.file_entry.id, self.file_entry.filepath, self.file_entry.filename, int(time.time())))
            self.image_hash = m.hexdigest()
            self.save()

        if not size in IMAGE_SIZE_MAPPING.keys():
            raise InvalidImageSize()
            
        if size == "original":
            print "Returning original"
            return self.file_entry.complete_filename()

        outputfile = os.path.join(settings.MEDIA_ROOT, 'generated', "%s_%s.jpg" % (self.image_hash, size))
        photo_url = '%s_%s.jpg' % (self.image_hash, size)
        if os.path.exists(outputfile):
            print "Returning photourl", photo_url
            return photo_url

        # Set our max thumbnail size in a tuple (max width, max height)
        THUMBNAIL_SIZE = IMAGE_SIZE_MAPPING[size]
  
        # Open original photo which we want to thumbnail using PIL's Image
        # object
        image = Image.open(self.file_entry.complete_filename())
    
        # Convert to RGB if necessary
        # Thanks to Limodou on DjangoSnippets.org
        # http://www.djangosnippets.org/snippets/20/
        if image.mode not in ('L', 'RGB'):
            image = image.convert('RGB')
    
        # We use our PIL Image object to create the thumbnail, which already
        # has a thumbnail() convenience method that contrains proportions.
        # Additionally, we use Image.ANTIALIAS to make the image look better.
        # Without antialiasing the image pattern artifacts may result.
        image.thumbnail(THUMBNAIL_SIZE, Image.ANTIALIAS)
    
        # Save the thumbnail
        image.save(outputfile)

        print "PHOTO URKL", photo_url
        return photo_url

    @classmethod
    def photoFromFile(cls, file_entry):
        """
        
        """
        md = file_entry.get_metadata()
        if not md:
            return None

        date = md.get('DateTime', file_entry.created_datetime)
        if not date:
            date = file_entry.creation_date

        return Photo(
            title = file_entry.filename,
            file_entry = file_entry,
            year = date.year,
            month = date.month,
            day = date.day,
            date_of_creation = date
        )
        
    def __unicode__(self):
        return self.title and self.title or self.file_entry.partial_filename()
    
    class Admin:
        pass

    def raw_present(self):
        """
        
        """
        pass
    
    def save_metadata(self):
        """
        
        """
        pass

    def created_datetime(obj):
        return obj.file_entry.created_datetime
    created_datetime.short_description = 'Creation date'    